#include <stdlib.h>

struct solution {
	int max;
	int curr;
	int *edge; // edge[n*N], ..., edge[(n+1)*N-1] save the nth solution
};

void init_solution (struct solution *solution);

void free_solution (struct solution *solution);

struct designability {
	int N;                     // Number of nodes
	int L;                     // Number of steps
	int *pathway;              // Biological process
	int activity;              // The activity of the given process
	int mode;                  // 0 Process with steady state ; 1 Cycle Process ; 2 Triggled Cycle Process
	int mode1;                 // 0 Budding Yeast Model ; 1 Fission Yeast Model (with self-activation)
	int mode2;                 // 0 Traditional SIM ; 1 Restriction I(reliable); 2 Restriction II(middle to middle); 3 Restriciton I and II
	int irflag;                // 1 Irreducible solution only
	int bdflag;                // 1 Breakdown the designability by number of the links
	int dgflag;                // 1/2 Breakdown the designability by number of the degrees(r<->g is counted for 2)
	int svflag;                // 1 Save all solutions into the struct solution
	int pnflag;                // 1 Print the solutions
	double NS;                 // Overall Designability for the given process
	int *NS2;                  // Individual Designability for each node
	int NS2_min;               // The minimum in the array NS2[]
	int *min_link;             // Number of links in the minimal network for each node
	int min_links;             // The sum of the array min_link[]
	int *links_dist;           // Individual Designability breakdown by the number of links
	double *Links_dist;        // Designability breakdown by the number of links
	int *degree_dist;          // Individual Designability breakdown by the solution's degree(in the solution space)
	double *Degree_dist;       // Designability breakdown by the solution's degree(in the solution space)
	struct solution *solution; // Solution for the given process
	int fix_edges;             // Number of fixed edges (only r or only g or only n)
	int free_edges;            // number of free edges (r/g/n don't matter)
};

/************************************************************************
int calc_design (struct designability *design)

Input

the following fields in the struct designability should be assigned before the call

N, L, pathway, mode, mode1, mode2, irflag, bdflag, dgflag, svflag, pnflag	

Output

the following fields in the struct designability should be fulfilled after the call

designability, Links_dist, Degree_dist, solution

Return Value	1 : Feasible

Attn            Links_dist, Degree_dist and the member NS2/min_link in the structure designability need to allocate memory space before calling this function. Links_dist's size is N*N+1, Degree_dist's is 2*N*N+1, NS2/min_link's is N and store the number of solution / minimum number of link in the solution for each node.
Attn2           For structure array solution[], just need call init_solution function for each element once before calling calc_design. main2.c is an example about how to use this new feature.
***********************************************************************/

int calc_design (struct designability *design);

struct solve_static {
	int *Og, *Or; /* Og/Or: Optional G/R */
	int *Rg0, *Rr0;
	int *edge;   /* To store the current solution */
};

struct solve_static *init_solve_static (int N);
void free_solve_static (struct solve_static *solve);

struct solve_dynamic {
	int *Rg, *Rr; /* Rg/Rr: Required G/R */
	int *Fg, *Fr; /* Fg/Fr: Forbidden G/R */
	int *order;  /* To store the order information of the node (we would shuffle the node order during the enumeration */
	int *edge;   /* To store the current solution (after reorder) */
	int *Og, *Or; /* To store the information of optional G/R (after reorder) */
};

struct solve_dynamic *init_solve_dynamic (int N);
void copy_solve_dynamic (int N, struct solve_dynamic *solve1, struct solve_dynamic *solve2);
void free_solve_dynamic (struct solve_dynamic *solve);

/***********************************************************************
void combine_dist (int N1, int N2, int dist[], double Dist[], int i)
This subroutine is used to calculate the links/degree distribution. N1 is the number of nodes and the array dist[N2+1] store the ith node' distribution. Array Dist[] stored the distribution up to the (i-1)th node. After the call, only array Dist[] is updated and stored the distribution up to the ith node.
***********************************************************************/
void combine_dist (int N1, int N2, int dist[], double Dist[], int i);
